home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
sound
/
moddis00.zip
/
mod_dis.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-03-19
|
33KB
|
1,127 lines
/* BEGIN DAVID LAI COPYRIGHT ********************************************* */
/*
(C) Copyright David Lai 1993, 1994. All rights reserved.
The source code is copyright by David Lai, however it is freely
distributable and released for unrestricted use. Users may copy or modify
this source code without charge, provided all copyright
notices remain intact in all the source code. Portions of the source code
copyright by their respective copyright holders and are covered
under different agreements, however the source code used has
specifically been marked distributable royalty-free.
You can do whatever you want with it, even charge money for it, if
you find a sucker willing to pay for it. This is not shareware, the program
is not crippled in any way, do not send money. You can e-mail comments
to the electronic mail address below, or fax to the fax number below.
If you add a feature thats useful, or do a new port, you can send
the context diffs to the e-mail address below. I may include it in
subsequent releases. Your code must specifically be marked
freely distributable, I will not include code marked otherwise.
THE SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
The source code is provided with no support and without any obligation on
the part of David Lai to assist in its use, correction,
modification or enhancement.
DAVID LAI SHALL HAVE NO LIABILITY WITH RESPECT TO THE
INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
OR ANY PART THEREOF.
In no event will David Lai be liable for any lost revenue
or profits or other special, indirect and consequential damages, even if
David Lai has been advised of the possibility of such damages.
David Lai
1370 McKendrie St
San Jose, CA 95126
fax: 408-241-4615
lai%fastfood@daver.bungi.com
*/
/* END DAVID LAI COPYRIGHT ********************************************* */
/* dis-assemble a mod file */
#include "misc.h"
#include "modcomp.h"
#include "wav.h"
#include "mod_disv.c" /* some initialized arrays */
/* ALLOW_CONTROLS will allow control characters and non-printing characters
in the name of the mod */
#undef ALLOW_CONTROLS
/* RPT_LENGTH_IS_INCR interprets the rpt_length field of samples as 1 more
than the actual number of words to repeat, for example:
length = 500
rpt_offset = 0
rpt_length = 500
The user really meant to say:
length = 500 (998 bytes of real sample)
rpt_offset = 0 (begin the repeat at the first byte of the real sample)
rpt_length = 499 (repeat entire 998 bytes of the sample)
Without RPT_LENGTH_IS_INCR, the above will generate warning message that
there is an attempt to repeat beyond the end of the sample (1000 bytes)
*/
#define RPT_LENGTH_IS_INCR
static struct sample samples[MAX_INSTRUMENTS];
static int channels=0, instruments=0, num_patterns;
static char mod_tag[MOD_TAGSIZE+1]="";
static char mod_name[MOD_NAME_LENGTH+1];
static int verbose=0;
static int adj, tagsize=MOD_TAGSIZE;
static unsigned char num_patterns_in_song, end_jump_pos;
static unsigned char pattern_table[PATTERN_TABLE_SIZE];
static uint32 file_size;
static int pattern_size;
static off_t fixed_size;
static char *mod_format="mod";
static int file_has_gaps=0;
static int dump_unused_patterns=0;
static uint32 wav_sample_rate=16574; /* .wav sample rate */
/* initially set to the middle C rate */
static int wav_info_flag = 1; /* dump INFO unless requested not to */
#define PATTERN_SPACE ((uint32)num_patterns * pattern_size)
#ifdef __STDC__
read_tag0(FILE *fi, off_t offset, char tag[MOD_TAGSIZE+1])
#else
read_tag0(fi, offset, tag) FILE *fi; off_t offset; char tag[MOD_TAGSIZE+1];
#endif
{
/* read the 4 byte tag at the offset specified and attempt to interpret */
if (fseek(fi, offset, SEEK_SET)!=0)
err_exit("Badly formed MOD file: cant seek to tag", NULL);
if (fread(tag, sizeof(char), MOD_TAGSIZE, fi) != MOD_TAGSIZE)
err_exit("Badly formed MOD file: cant read tag",NULL);
tag[MOD_TAGSIZE]='\0';
if (strcmp(tag,"M.K.")==0 || strcmp(tag,"FLT4")==0 || strcmp(tag,"M!K!")==0 ||
strcmp(tag,"4CHN")==0 || strcmp(tag,"M&K!")==0 )
{
channels = 4;
return 1; /* success */
}
else if (strcmp(tag,"6CHN")==0)
{
channels = 6;
return 1; /* success */
}
else if (strcmp(tag,"8CHN")==0 || strcmp(tag,"OCTA")==0)
{
channels = 8;
return 1; /* success */
}
else
return 0; /* dont know this tag */
}
#ifdef __STDC__
read_tag(FILE *fi)
#else
read_tag(fi) FILE *fi;
#endif
{
/* read and interpret tag to determine file format */
char tag[MOD_TAGSIZE+1], tag15[MOD_TAGSIZE+1];
/* check if it is a 31 instr file first */
if (read_tag0(fi, TAG_OFFSET_31, tag)==1)
{
instruments = 31;
strcpy(mod_tag, tag);
return 1;
}
/* try again with 15 instr */
if (read_tag0(fi, TAG_OFFSET_15, tag15)==1)
{
instruments = 15;
strcpy(mod_tag, tag15);
return 1;
}
/* take a guess that it is 4 track */
if (verbose) fprintf(stderr, "Warning: Unknown tag 31=%s 15=%s\n", tag, tag15);
fprintf(stderr,"Unknown mod format - assuming -c 4 -i 15\n");
channels = 4;
instruments = 15;
tagsize = 0;
#if 0
{
int c;
/* check if there is printable chars at location 470 */
if (fseek(fi, CHECK_31_INST_OFFSET, SEEK_SET)!=0)
err_exit("Unable to seek to check", NULL);
c=getc(fi);
if (isascii(c) && isprint(c)) /* this test may not work all the time */
{
instruments = 31;
strcpy(mod_tag, tag15);
}
else
{
instruments= 15;
strcpy(mod_tag, tag15);
}
}
#endif
return 1;
}
void
#ifdef __STDC__
verify_format(FILE *fi)
#else
verify_format(fi) FILE *fi;
#endif
{
/* verify the name of the mod is valid */
int i,j;
uint32 total_sample_size;
if (fseek(fi, 0L, SEEK_SET)!=0)
err_exit("Badly formed MOD file", NULL);
if(fread(mod_name, sizeof(char), MOD_NAME_LENGTH, fi) != MOD_NAME_LENGTH)
err_exit("Badly formed MOD file - mod name", NULL);
mod_name[MOD_NAME_LENGTH]='\0';
/* check all chars are valid */
for (i=0; i< MOD_NAME_LENGTH; i++)
if ((!isascii(mod_name[i])) || (!isprint(mod_name[i]) && mod_name[i]!='\0'))
#ifndef ALLOW_CONTROLS
err_exit("Bad mod name, character 0x%x",(unsigned char)mod_name[i]);
#else
fprintf(stderr, "Bad mod name, character 0x%x\n",(unsigned char)mod_name[i]);
#endif
/* verify that all sample headers are OK */
for (j=0; j< instruments; j++)
{
if (fseek(fi, SAMPLE_HEADER_OFFSET +
SAMPLE_HEADER_LENGTH *j, SEEK_SET)!=0)
err_exit("Badly formed MOD file, cant read sample headers", NULL);
if (fread( samples[j].name, sizeof(char), SAMPLE_NAME_SIZE, fi) !=
SAMPLE_NAME_SIZE)
err_exit("Cant read sample name %d",j);
samples[j].name[SAMPLE_NAME_SIZE]='\0';
if (verbose > 1)
{
for(i=0; samples[j].name[i]!='\0' && i< SAMPLE_NAME_SIZE; i++)
if (!isprint(samples[j].name[i]) && isascii(samples[j].name[i]))
fprintf(stderr,"Warning: Bad character in sample #%d name, character 0x%x in %s\n",
j, (unsigned char)samples[j].name[i], samples[j].name);
}
samples[j].length = rbshort(fi);
samples[j].orig_length = samples[j].length;
if (samples[j].length == (SAMPLE_IGNORE_BYTES / 2))
{
if (verbose > 1)
fprintf(stderr,"Warning: zeroing sample %d length (was %u)\n",
j,samples[j].length);
samples[j].length = 0;
adj+= (SAMPLE_IGNORE_BYTES / 2);
/* adjustment for filelength checks */
}
if (fread( &samples[j].finetune, 1, 1, fi)!=1)
err_exit("Cant read sample %d's finetune", j);
/* sign extend finetune */
samples[j].finetune = SIGN_EXT_NIBBLE(samples[j].finetune);
if (fread( &samples[j].volume, 1, 1, fi)!=1)
err_exit("Cant read sample %d's volume", j);
if (samples[j].volume > 64)
{
if (verbose)
fprintf(stderr,"Warning: volume for sample %d out of range %d, set to 64\n",j, samples[j].volume);
samples[j].volume = 64;
}
samples[j].rpt_offset = rbshort(fi);
samples[j].rpt_leng